#include <iostream>
#include "smartdb.hpp"
#include <boost/timer.hpp>

#include <rapidjson/prettywriter.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/document.h>
#include <rapidjson/rapidjson.h>

using namespace std;

void TestJson(SmartDB& db, const string& sqlinsert)
{
    //这里通过jsoncpp封装类来简化json对象的创建
    rapidjson::StringBuffer buf;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
    writer.StartArray();
    for (size_t i = 0; i < 10; i++)
    {
        writer.StartObject();
        writer.String("ID");
        writer.Int(i + 1);

        writer.String("Name");
        writer.String("Peter");

        writer.String("Address");
        writer.String("Zhuhai");
        writer.EndObject();
    }
    writer.EndArray();

    auto r = db.ExcecuteJson(sqlinsert, buf.GetString());
    if (r) cout<<"json insert succ!"<<endl;
    else
        cout<<"json insert fault!"<<endl;
}

#if 1
void TestCreateTable()
{
    SmartDB db;
    db.Open("test.db");

    const string sqlcreat = "CREATE TABLE if not exists PersonTable(ID INTEGER NOT NULL, Name Text, Address Text);";
    if (!db.Excecute(sqlcreat))
        return;

    const string sqlinsert = "INSERT INTO PersonTable(ID, Name, Address) VALUES(?, ?, ?);";
    int id = 2;
    string name = "Peter";
    string city = "zhuhai";
    blob bl = { city.c_str(), city.length() + 1 };
    if (!db.Excecute(sqlinsert, id, "Peter", "zhengzhou"))
        return;

    TestJson(db, sqlinsert);

    //auto r = db.ExcecuteTuple(sqlinsert, std::forward_as_tuple(id, "Peter", bl));
    //char* json;
    //rapidjson::Document doc;
    string strQery = "select * from PersonTable";
    //for (size_t i = 0; i < 10000; i++)
    {
        auto p = db.Query(strQery);
        rapidjson::Document doc;
        doc.Parse<0>(p.c_str());
        //遍历查询结果
        for ( int i = 0; i < doc.Size(); ++i )
        {
            const rapidjson::Value& object = doc[i];
            printf("%d. Id: %d  name: %s, address: %s\n",i,
                object["ID"].GetInt(), object["Name"].GetString(),object["Address"].GetString());
        }

    }

    try {
        //const string str = "select Address from PersonTable where name='wuwei'";
        const string str = "select max(ID) from PersonTable ";
        //string pname;

        auto ret = db.ExecuteScalar(str);

        //auto l = strlen(pname.c_str());
        cout <<"exec sql ret : "<< ret << endl;

    }
    catch (...)
    {
        cout<<"not find this para" <<endl;
    }

}
#endif

void TestPerformance()
{
    SmartDB db;
    db.Open("test.db");   //打开数据库
    const string sqlcreat = "CREATE TABLE if not exists TestInfoTable(ID INTEGER NOT NULL, KPIID INTEGER, CODE INTEGER, V1 INTEGER, V2 INTEGER, V3 REAL, V4 TEXT);";
    if (!db.Excecute(sqlcreat))  //执行sql语句
        return;

    boost::timer t;
    const string sqlinsert = "INSERT INTO TestInfoTable(ID, KPIID, CODE, V1, V2, V3, V4) VALUES(?, ?, ?, ?, ?, ?, ?);";
    bool ret = db.Prepare(sqlinsert);
    db.Begin();
    char buf[5] = {1,2,3,4,5};
    blob bl;
    bl.pBuf = buf;
    bl.size = sizeof(buf);
    for (size_t i = 0; i < 10; i++) //00000
    {
        ret = db.ExcecuteArgs(i, i, i, i, i, i + 1.25, "it is a test");
        if (!ret)
            break;
    }

    if (ret)
        db.Commit(); //提交事务
    else
        db.RollBack(); //回滚

    cout << t.elapsed() << endl;
    t.restart();
    //100w 3.5-4秒左右

    auto p = db.Query("select * from TestInfoTable");
    cout << t.elapsed() << endl;
    cout << "size: " << p.size() << endl;
    //100W 4秒左右

      rapidjson::Document doc;
      doc.Parse<0>(p.c_str());
      //打印到屏幕
      //cout<<"the json output:"<<endl;
     //cout<<buffer.GetString()<<endl;

    //遍历查询结果
    if (doc.Size() > 0)
    {
        for ( int i = 0; i < doc.Size(); ++i )
        {
            const rapidjson::Value& object = doc[i];
            printf("%d. Id: %d  KpiId: %d, v3: %f, v4: %s\n",i,
                object["ID"].GetInt(), object["KPIID"].GetInt(),object["V3"].GetDouble(),object["V4"].GetString());
        }
    }
}


void TestBlobmance()
{
    SmartDB db;
    db.Open("test.db");   //打开数据库
    const string sqlcreat = "CREATE TABLE if not exists TestBlob(ID INTEGER NOT NULL, KPIID INTEGER, V4 blob);";
    if (!db.Excecute(sqlcreat))  //执行sql语句
        return;

    boost::timer t;
    const string sqlinsert = "INSERT INTO TestBlob(ID, KPIID, V4) VALUES(?, ?, ?);";
    bool ret = db.Prepare(sqlinsert);
    db.Begin();
    char buf[] = {1,2,3,4,5,0};
    blob bl;
    bl.pBuf = buf;
    bl.size = sizeof(buf);
    for (size_t i = 0; i < 10; i++) //00000
    {
        ret = db.ExcecuteArgs(i, i, bl);
        if (!ret)
            break;
    }

    if (ret)
        db.Commit(); //提交事务
    else
        db.RollBack(); //回滚

    cout << t.elapsed() << endl;
    t.restart();
    //100w 3.5-4秒左右

    auto p = db.Query("select * from TestBlob");
    cout << t.elapsed() << endl;
    cout << "size: " << p.size() << endl;
    //100W 4秒左右

      rapidjson::Document doc;
      doc.Parse<0>(p.c_str());
      //打印到屏幕
      //cout<<"the json output:"<<endl;
     cout<<p<<endl;

    //遍历查询结果
    if (doc.Size() > 0)
    {
        for ( int i = 0; i < doc.Size(); ++i )
        {
            const rapidjson::Value& object = doc[i];
            const char *p = object["V4"].GetString();
            printf("%d. Id: %d  KpiId: %d, v4: %d, %d,%d,%d,%d, %d\n",i,
                object["ID"].GetInt(), object["KPIID"].GetInt(),p[0],p[1], p[2],p[3],p[4],p[5]);
        }
    }
}
int main()
{
    cout << "Hello World!" << endl;

    TestCreateTable();
    TestPerformance();
    TestBlobmance();
    getchar();
    return 0;
}
